package com.youlu.campus.service.english;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.exception.EnglishReceiveCaException;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.CaCollectReq;
import com.youlu.campus.entity.VO.res.CaCollectRes;
import com.youlu.campus.entity.english.UserCompetition;
import com.youlu.campus.entity.english.UserCompetitionQaCa;
import com.youlu.campus.entity.english.vo.request.CompetitionCaCollectRequest;
import com.youlu.campus.entity.english.vo.response.CompetitionUserInviteResponse;
import com.youlu.campus.service.ca.CaTemplateService;
import com.youlu.campus.service.ca.impl.CaCertificateConfigService;
import com.youlu.campus.service.ca.impl.CaCollectService;
import com.youlu.campus.service.ca.impl.CertificateActivityConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserCompetitionQaCaService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserCompetitionService userCompetitionService;

    @Autowired
    private CertificateActivityConfigService certificateActivityConfigService;

    @Autowired
    private CaCertificateConfigService caCertificateConfigService;

    @Autowired
    private CaTemplateService caTemplateService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private CaCollectService caCollectService;

    @Autowired
    private CompetitionUserInviteService competitionUserInviteService;

    private final String CA_CERTIFICATE_LOCK = "ca:certificate:english:lock:%s:%s:%s:%s";

    public CaCollectRes caCollect(CompetitionCaCollectRequest competitionCaCollect){
        String activityGroupId = competitionCaCollect.getActivityGroupId();
         String caType = competitionCaCollect.getCaType();
        String caLevel = competitionCaCollect.getCaLevel();
        UserPO currentUser = competitionCaCollect.getCurrentUser();
        String activityId = "";
         log.info("【英语大赛-电子证书】-用户-> {} 正在领取组别 - > {} 证书类型 - > {} 证书等级 ->{}",currentUser.getId(),activityGroupId,
                 caType,caLevel);
         if(competitionCaCollect.getQaReceive()){//答题领取电子证书
             UserCompetitionQaCa userCompetitionQaCa = findByUserId(currentUser.getId(),activityGroupId,caType,caLevel);
             if(Objects.isNull(userCompetitionQaCa)){
                 throw new BusinessException("对不起，您不满足条件领取证书");
             }
              activityId = userCompetitionQaCa.getActivityId();
         }else{
             activityId = competitionCaCollect.getActivityId();
             CompetitionUserInviteResponse competitionUserInvite = competitionUserInviteService.caInvite(activityId, currentUser.getId());
             if(Objects.isNull(competitionUserInvite)){
                 throw new BusinessException("对不起，您不满足条件领取证书");
             }
             if(competitionUserInvite.getInviteValue()==0){
                 throw new BusinessException("对不起，您不满足条件领取证书");
             }
             if(!competitionUserInvite.getCaReceive()){
                 throw new BusinessException("对不起，您不满足条件领取证书");
             }
         }
        UserCompetition userCompetition = userCompetitionService.findByUserId(currentUser.getId());
         if(Objects.isNull(userCompetition)){
             throw new BusinessException("对不起，您未填写报名信息");
         }
        return commonCaReceive(currentUser,activityId,caType,caLevel,userCompetition);
    }

    public CaCollectRes commonCaReceive(UserPO currentUser,String activityId,String caType,String caLevel,UserCompetition userCompetition){
        CertificateActivityConfig certificateActivityConfig =
                certificateActivityConfigService.findByActivityIdAndBizType(activityId, caType);
        CaCertificateConfig caCertificateConfig =
                caCertificateConfigService.findByActivityIdAndCaTypeAndCaLevel(activityId, caType, caLevel);
        CaTemplate caTemplate = caTemplateService.detail(caCertificateConfig.getTemplateId());
        String caTime = certificateActivityConfig.getCaTime();
        String letterStart = certificateActivityConfig.getLetterStart();
        String lockKey = String.format(CA_CERTIFICATE_LOCK, activityId, currentUser.getId(), caType,
                caLevel);
        log.info("【证书编号】获取锁信息->{}", lockKey);
        Boolean existKey = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 2L, TimeUnit.SECONDS);
        if (Objects.nonNull(existKey)&&!existKey) {
            throw new BusinessException("对不起哦，服务繁忙,稍后重试");
        }
        if(StringUtils.isBlank(caTime)){
            caTime = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }
        CaCollectReq caCollectReq = new CaCollectReq();
        caCollectReq.setActivityId(activityId);
        caCollectReq.setCaType("1");
        caCollectReq.setTaskBizType(caType);
        caCollectReq.setCaLevel(caLevel);
        caCollectReq.setCaTime(caTime);
        caCollectReq.setCurrentUser(currentUser);
        String certificateNo = caCollectService.buildCertificateNo(caCollectReq, letterStart);
        CaCollectRes caCollect = new CaCollectRes();
        caTemplate.setCaName(caCertificateConfig.getCertificateName());
        caCollect.setCaTemplate(caTemplate);
        caCollect.setCertificateNo(certificateNo);
        caCollect.setUniversityName(userCompetition.getUniversityName());
        caCollect.setUserName(userCompetition.getName());
        caCollect.setCaTime(caTime);
        ActivityUserRecord activityUserRecord = new ActivityUserRecord ();
        activityUserRecord.setCaLevel(caLevel);
        activityUserRecord.setTaskBizType(caType);
        activityUserRecord.setName(userCompetition.getName());
        activityUserRecord.setUniversityName(userCompetition.getUniversityName());
        activityUserRecord.setCaTime(caTime);
        activityUserRecord.setMobile(userCompetition.getMobile());
        activityUserRecord.setActivityId(activityId);
        Query query = new Query();
        query.addCriteria(Criteria.where("certificateNo").is(certificateNo));
        UserCaRecord userCaRecord = this.mongoTemplate.findOne(query, UserCaRecord.class);
        if(Objects.nonNull(userCaRecord)){
            caCollect.setCaTime(userCaRecord.getCaTime());
        }
        Date pubDate = DateUtil.parseDate(caCollect.getCaTime());
        String caTimeStr = DateUtil.format(pubDate,"yyyy年M月d日");
        caCollect.setCaTime(caTimeStr);
        caCollectService.caBuild(certificateNo,activityUserRecord,caTemplate);
        return caCollect;
    }

    public List<UserCompetitionQaCa> caList(String userId){
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        List<UserCompetitionQaCa> caList = this.mongoTemplate.find(query, UserCompetitionQaCa.class);
        if(CollectionUtils.isEmpty(caList)){
            throw new EnglishReceiveCaException("您暂无可领取的证书，请去参加全球大使招募活动，可获得证书");
        }
        List<UserCompetitionQaCa> groupNameList = Lists.newArrayList();
        Map<String, List<UserCompetitionQaCa>> caMapGroup = caList.stream().collect(Collectors.groupingBy(UserCompetitionQaCa::getActivityGroupName));
        caMapGroup.forEach((group,item)->{
            Map<String, List<UserCompetitionQaCa>> caTypeMap = item.stream().collect(Collectors.groupingBy(UserCompetitionQaCa::getCaType));
            caTypeMap.forEach((caTypeLevel,caLevelItem)->{
                UserCompetitionQaCa groupName = new UserCompetitionQaCa();
                groupName.setActivityGroupName(group);
                groupName.setCaTitle(caTypeLevel);
                groupName.setCaTypeLevel(caLevelItem);
                groupNameList.add(groupName);
            });
        });
        return groupNameList;

    }





    /**
     * 修改新增用户答题证书信息
     * @param userCompetitionQaCa
     */
    @Async
    public void save(UserCompetitionQaCa userCompetitionQaCa) {
        String activityGroupId = userCompetitionQaCa.getActivityGroupId();
        String userId = userCompetitionQaCa.getUserId();
        String caLevel = userCompetitionQaCa.getCaLevel();
        String caType = userCompetitionQaCa.getCaType();
        UserCompetitionQaCa userCompetitionQaCaExist = findByUserId(userId,activityGroupId,caType,caLevel);
        if (Objects.isNull(userCompetitionQaCaExist)) {
            UserCompetition userCompetition = userCompetitionService.findByUserId(userId);
            if (Objects.nonNull(userCompetition)) {
                userCompetitionQaCa.setName(userCompetition.getName());
                userCompetitionQaCa.setMobile(userCompetition.getMobile());
                userCompetitionQaCa.setUniversityId(userCompetition.getUniversityId());
                userCompetitionQaCa.setUniversityName(userCompetition.getUniversityName());
                this.mongoTemplate.save(userCompetitionQaCa);
            }
        }
    }

    public UserCompetitionQaCa findByUserId(String userId,String activityGroupId,String caType,String caLevel){
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityGroupId").is(activityGroupId));
        query.addCriteria(Criteria.where("caType").is(caType));
        query.addCriteria(Criteria.where("caLevel").is(caLevel));
        return this.mongoTemplate.findOne(query, UserCompetitionQaCa.class);
    }



}
